///********************************************************************
///* Copyright © 2011 fishr (fishr.flash@gmail.com)  
///********************************************************************


package su.fishr.effects.prismavision 
{
	import flash.display.Bitmap;
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	import su.fishr.display.SmoothResizeDObject;
	import su.fishr.effects.prismavision.elem.ModelTriangle;
	import su.fishr.geom.CuttingDObject;
	
	
   /**
	 * Хранит массив изображений, дополняет или заменяет
	 * его поступающими изображениями в зависимости от булевой
	 * перем.
	 * Нарезает на фрагменты очередное изображение, помещает 
	 * в геттер. При обращении к геттеру создает новый массив
	 * фрагментов из следующего по очереди изображений.
	 * Нарезанные изображения хранит в массиве помещая в геттер очередное,
	 * если процедура нарезки закончена, просто закольцовывает подачу
	 * массивов фрагментов.
	 * Если параметры разделения изобр. на фрагменты изменены, перенарезает
	 * исходные изображения.
	 * Нарезая фрагменты назначает им координаты нахождения
	 * в исходном изображении, вьюер, же считывает эти координаты
	 * и назначает контейнерам их хранящих, изменяя координаты
	 * полученных фрагментов сообразно своим усмотрениям.
	 * 
	 * @version                1.0
	 * @playerversion          Flash 9
	 * @langversion            3.0
	 * @author                 fishr
	 * @created                15.08.2011 18:27
	 * @since                  15.08.2011 18:27
	 */
	internal class PV_model extends EventDispatcher
	{
		
	/**-------------------------------------------------------------------------------
	* 
	*	   						V A R I A B L E ' S 	
	* 
	* --------------------------------------------------------------------------------
	*/
	//{
	    static public const AUTHOR:String = "fishr (fishr.flash@gmail.com)";
		static public const CREATE_DATAS:String = "createDatas";
		static public const GO_UPLOAD_PARAM:String = "goUploadParam";
		private var _arrImg:Array;
		///текущее значение выбранного элемента
		///массива изображений для нарезки
		private var _nowImgNb:int;
		private var _wPrisma:int;
		private var _countRows:int;
		private var _savingsMemory:Boolean;
		private var _arrFragments:Array;
		private var _timeDelay:Timer;
		private var _delay:Number = .1;
		private var _duration:Number;
		private var _fps:int;
		private var _manualStart:Boolean = false;
		private var _fwdSteps:Array;
		private var _backSteps:Array;
		private var _vertical:Boolean;
		private var _fragmentsHolder:Array = new Array();
		private var _maskFragments:Array = new Array();
		private var _arrMasksLaer:Array;
		private var _useFilters:Boolean;
		///степень сглаживания повернутых плоскостей
		private var _smooth:int;
		
	//}
	
	/**-------------------------------------------------------------------------------
	* 
	*	 						P R O P E R T I E S 	
	* 
	* --------------------------------------------------------------------------------
	*/
	//{
		public function set arrImg(value:Array):void 
		{
			_arrImg = value;
		}

		public function get arrImg():Array 
		{
			return _arrImg;
		}
		
		public function get nowImgNb():int 
		{
			return _nowImgNb;
		}
		
		public function set nowImgNb(value:int):void 
		{
			_nowImgNb = value;
		}
		public function get wPrisma():int 
		{
			return _wPrisma;
		}
		
		public function set wPrisma(value:int):void 
		{
			_wPrisma = value;
		}
		
		public function get countRows():int 
		{
			return _countRows;
		}
		
		public function set countRows(value:int):void 
		{
			_countRows = value;
		}
				
		public function get arrFragments():Array 
		{
			return _arrFragments;
		}
		
		public function get delay():Number 
		{
			return _delay;
		}
		
		public function set delay(value:Number):void 
		{
			if ( _manualStart === true ) return;

			_delay = value;

			if ( _timeDelay )
			{
				_timeDelay.stop();
				_timeDelay.removeEventListener( TimerEvent.TIMER, delayEndHandler );
				
			}
			
			_timeDelay = new Timer( _delay );
			_timeDelay.addEventListener( TimerEvent.TIMER, delayEndHandler );
			
			
		}
		

		
		public function get duration():Number 
		{
			return _duration;
		}
		
		public function set duration(value:Number):void 
		{
			_duration = value;
		}
		
		public function get fps():int 
		{
			return _fps;
		}
		
		public function set fps(value:int):void 
		{
			_fps = value;
		}
		
		public function get manualStart():Boolean 
		{
			return _manualStart;
		}
		
		public function set manualStart(value:Boolean):void 
		{
			
			_manualStart = value;
			
			if ( _manualStart === true)
			{
				if ( _timeDelay )
				{
					_timeDelay.removeEventListener( TimerEvent.TIMER, delayEndHandler );
				}
				delayEndHandler(null);
			}
			else
			{
				_timeDelay.addEventListener( TimerEvent.TIMER, delayEndHandler );
			}

			
		}
		
		public function get fwdSteps():Array 
		{
			return _fwdSteps;
		}
		
		public function get backSteps():Array 
		{
			return _backSteps;
		}
		
		public function get vertical():Boolean 
		{
			return _vertical;
		}
		
		public function set vertical(value:Boolean):void 
		{
			_vertical = value;
		}
		
		public function get arrMasksLaer():Array 
		{
			return _arrMasksLaer;
		}
		
		public function get useFilters():Boolean 
		{
			return _useFilters;
		}
		
		public function set useFilters(value:Boolean):void 
		{
			_useFilters = value;
		}
		
		public function set smooth(value:int):void 
		{
			_smooth = value;
		}
		public function get smooth():int 
		{
			return _smooth;
		}

		

	//}
	/**-------------------------------------------------------------------------------
	* 
	*								P U B L I C 	
	* 
	* --------------------------------------------------------------------------------
	*/
	//{
		public function PV_model(target:IEventDispatcher = null)
		{
			super(target);
			
		}
		
		///нарезаем очередное изображение на фрагменты
		public function createDatas():void 
		{
			///TODO trace
			////////////////////////// T R A C E ///////////////////////////////
			var d:Date = new Date();
			trace(d.valueOf() + ". PV_model, createDatas, _nowImgNb : " + _nowImgNb);
			//////////////////////// E N D  T R A C E //////////////////////////
			var grads:int = 120;
			var wdth:int = _vertical === true? _arrImg[_nowImgNb].width / _countRows : _wPrisma;
			var hght:int = _vertical === true? _wPrisma : _arrImg[_nowImgNb].height / _countRows;
			
			
			_fwdSteps = addSteps( -  grads );
			_backSteps = addSteps( grads );

			if ( _useFilters === true )
			{
				var maskLaer:Bitmap;
				
				/// сглаживаем маску.
				maskLaer = SmoothResizeDObject.strongSmoothing( _arrImg[_nowImgNb], _smooth );
				_arrMasksLaer = CuttingDObject.cuttingDObject( maskLaer, wdth , hght, _vertical);
				
			}
			
			_arrFragments = CuttingDObject.cuttingDObject( _arrImg[_nowImgNb], wdth , hght, _vertical);
			_nowImgNb = _nowImgNb < _arrImg.length - 1? _nowImgNb + 1: 0;
			_fragmentsHolder.push( _arrFragments );
			_maskFragments.push( _arrMasksLaer );
			
			
			
			if ( _fragmentsHolder[2] ) 
			{
				destroyOldFragments(_fragmentsHolder.shift());
			}
			
			
			this.dispatchEvent( new Event( PV_model.CREATE_DATAS ));
			
		}
		
		public function startTimer():void
		{
			_timeDelay.addEventListener( TimerEvent.TIMER, delayEndHandler );
			_timeDelay.start();
		}
		
		public function delayEndHandler(e:TimerEvent):void 
		{
			_timeDelay.reset();
			_timeDelay.stop();
			this.dispatchEvent( new Event( GO_UPLOAD_PARAM ));
			
		}

	//}
	
	/**-------------------------------------------------------------------------------
	* 
	*								P R I V A T E 	
	* 
	* --------------------------------------------------------------------------------
	*/	
	//{

		
		

		
		private function addSteps( grads:int):Array
		{
			var countStep:int = _fps * _duration;
			var gradStep:Number = grads / countStep; 
			var triangle:ModelTriangle = new ModelTriangle();
			var arrSteps:Array = new Array();
			var oneStep:Array = new Array();
			
			for ( var i:int = 0; i < countStep; i++ )
			{
				oneStep = triangle.rotateModel( gradStep );
				arrSteps.push( oneStep );
			}
			
			return arrSteps;
		}
		
		///TODO: Дополнить методом уничтожающим все фрагменты (при выходе из приложения).
		private function destroyOldFragments(arr:Array):void 
		{
			var bitmap:Bitmap;
			
			for ( var i:int = 0; i < arr.length; i++ )
			{
					while ( arr[i].length )
					{
						bitmap = arr[i].shift();
						bitmap.bitmapData.dispose();
						bitmap.bitmapData = null;
						bitmap = null;
					}
			}
			
			if ( _maskFragments[2] )destroyOldFragments( _maskFragments.shift());
			
		}
		
		
		
	//}
		
		
	}

}